This document explains how to use FW_CEditView to implement text-edit views in your part. On Macintosh FW_CEditView is a wrapper for TextEdit, the basic text manager described in Inside Macintosh “Text”. It is well suited for handling editable text items in dialog boxes and small text fields that don’t require formatting. It supports multi styled text and also the Script manager for non Roman characters. However it is not intended to manipulate lengthy documents or text requiring more than rudimentary formatting. If your part requires a real text processor you will need to port existing code you may have or work with a commercial text processor engine. We plan to provide better text processing support in future releases, including support for TSM, the Text Service Manager.
ODF Form is our show-case example for edit views, run it and look at the source code in ODFDev:Form:Sources.
Adding an Edit View to Your Frame
Creation by program or by resource
If you are creating your views by program you can use one of the two class constructors:
FW_CEditView (Environment* ev,
FW_CSuperView* container,
const FW_CRect& bounds,
ODID viewId,
const FW_CString& text,
const FW_CFont& font = FW_kNormalFont,
short maxChars = FW_MAXINT16,
unsigned short attributes = FW_CEditView::kDrawBox +
They both require the usual view attributes, container, view id and bounds. The first one lets you enter an initial string and they both define default values for the other attributes.
The following listing shows how the Form example creates its 4 edit views aligned vertically (in CFormView::CreateSubViews) :
• A view id, required to be able to access this object later and read or change its text.
• A bounds rectangle, placing the edit box in its parent view.
• A binding flag. It should be initialized to FW_kFixedBounds in order to keep the edit view in a fixed position when its parent is resized. You can change that by calling FW_CView::SetBindings or by using a different value in the resource. For instance, to make the edit view grow horizontally with its parent use the value FW_kLeftBinding + FW_kRightBinding + FW_kTopBinding + FW_kFixedHeight. Binding constants are defined in ODF:Framewrk:FWViews:Include:FWViews.k
• A maximum number of characters. A typical 1 line edit field should have a reasonable limit, this prevents your program from having to do extra checking. A scrolling edit field can use the maximum number allowed by entering -1, this will be converted to FW_MAXINT16 = 32767.
• A text attributes flag. This value is a combination of the enums defined in FW_CEditView (you must use a numeric value in the .fr file because the enums are not defined):
// EditView attributes
enum AttrEnum
{
kDrawBox = 0x01, // draw a 1 pixel frame
kReadOnly = 0x02, // not implemented yet
kWordWrap = 0x04, // wrap long lines
kAutoScroll = 0x08, // scroll when text out of view
kOutlineHilite = 0x10, // show selection in inactive text edit
kTextBuffering = 0x20, // for 2-byte scripts
kInlineInput = 0x40, // use keyboard input method
kTextServices = 0x80 // see Inside Macintosh: Text
};
Note: see Inside Macintosh:Text for more information on the last 5 flags.
For a typical 1 line edit field you should use kDrawBox + kAutoScroll = 9. By using these constants, you allow the text to scroll horizontally, the right border of the “destination rectangle” where the text flows is initialized to a large value.
For a multi-lines edit view you should use kDrawBox + kWordWrap + kAutoScroll = 13. When kWordWrap is set the destination rectangle is the same as the view rectangle.
• A font object. The class constructors use FW_kNormalFont by default which maps to Geneva 12 on Macintosh. In your edit-view resource you can use a macro such as FW_NORMAL_FONT (defined in FWViews.fr) to specify the font, or you can define your own macro at the top of the .fr file:
Important! The insertion point doesn’t blink until you add an FW_CIdler object to the frame containing the edit view. Having an idler attached to your part is not enough, only the frame can propagate the null event to its current target, i.e. the active edit view.
CFormFrame::CFormFrame(...)
{
// We must create an idler to see the caret blink in text-edit views
fIdler = FW_NEW(FW_CIdler, (this, 15));
fIdler->RegisterIdle(ev);
}
CFormFrame::~CFormFrame()
{
delete fIdler;
}
The exceptions to this rule are dialog frames because an idler object is already created by FW_CDialogFrame.
Tabbing between edit views
When a frame contains several edit views you can implement easily a tabbing behavior by creating an FW_CViewTabber object. This cannot be done in resources in the current release, instead do it in your frame’s PostCreateViewFromStream method (or the CreateSubViews method if you are not using resources):
// ----- Add a ViewTabber event handler to the frame
fViewTabber = new FW_CViewTabber(ev, this);
You must not delete this object in the frame’s destructor, it will be done for you because this is an attached event handler.
A frame containing this event handler traps the Tab key and selects the next view which wants to be the target (or the previous one if the Shift key was pressed too). This allows the user to circulate among edit views within the same frame, and also circulate among any other view that can respond to keyboard events such as list boxes. The Tab may be replaced by another key with the FW_CViewTabber::SetTabbingKey method. The current tab key is returned by GetTabbingKey.
Note: as for text idling, frames derived from FW_CDialogFrame have an FW_CViewTabber object already created for them.
FW_CEditView Reference
Getters methods
FW_Boolean HasBox() const;
FW_Boolean HasWordWrap() const;
FW_Boolean HasAutoScroll() const;
unsigned short GetEditAttributes() const;
These methods return information on the text edit attributes.
FW_CString GetText(Environment* ev) const;
Use GetText to read the content of the edit view in a dynamic string, ODF will adjust its size properly.
SetText replaces the entire content with the new text (up to the maximum number of bytes allowed) and redraws the edit view. The initial text can be set also in the constructor or in resource.
virtual void ClearText(Environment* ev);
ClearText empties the edit view and redraws it.
virtual void InsertText(Environment* ev, const FW_CString& textToInsert, short offset);
This inserts some text after the position offset and redraws the edit view.
Use GetSelectionRange if you want to get the start and end offsets of the current selection, without copying the text. An empty selection is when startOffset == endOffset.
void SelectText(Environment* ev, short startOffset, short endOffset)
SelectText changes the current selection and updates the edit view. Use endOffset = FW_MAXINT16 to extend the selection until the end.
void SelectAll(Environment* ev);
SelectAll selects the entire text. This is used by FW_CViewTabber when activating an edit view during tabbing.
DoCharKey and DoVirtualKey are inherited from FW_MEventHandler. You can override them to handle specific keys. DoCharKey calls InputCharKey with just a char argument, this can be used to modify the character being typed. See for example CPwdEditView::DoCharKey in the Form sample.
This is called in response to an Edit menu command: Cut, Copy, Paste, Clear and SelectAll. useScrap is true when the Macintosh Scrap is used instead of the OpenDoc clipboard. The Form’s class CEditViewCommand uses doTECommand to implement undo/redo actions.
Adding More Features to FW_CEditView
Key filters
Two event handler classes allow you to filter out all characters not belonging to a specific set. The following line attaches an event handler accepting only alpha-numeric characters (plus backspace and the arrow keys):
FW_CAlphaNumFilter* filter1 = new FW_CAlphaNumFilter(ev, myEditView);
In the same way this line attaches an event handler accepting only numeric characters:
FW_CIntegerFilter* filter2 = new FW_CIntegerFilter(ev, myEditView);
Note: attached event handlers are deleted automatically with their parent.
Invisible characters
The Form sample contains a password dialog with an edit view class that replaces each character with a “bullet”. A separate invisible edit view contains the real text being edited so that backspace and arrow keys are supported. See the file :ODFDev:Form:Sources:Dialog.cpp.
Scrolling
Another custom class in Form, CScrollEdit, demonstrates how to add scroll bars to an edit view (the ODF classes FW_CScroller and FW_CScrollBarScroller cannot be used because they handle only the content view in this release). You can reuse CScrollEdit directly in your part. See the file :ODFDev:Form:Sources:ScrollEd.cpp.
Undo/Redo support
Finally, Form provides an example of Undo/Redo support in edit views with the classes: CEditViewCommand, CEditViewSelection and CEditViewSelContent. See the file :ODFDev:Form:Sources:EditCmd.cpp.
These classes allow you to support Undo/Redo actions even if the edit views do not belong to your part’s content. In ODF version 1 the Form sample doesn’t maintain any content made of the form’s data, the Form’s presentation doesn’t have any selection object; in this case you must create a local selection object for each edit view as it is done in the method CScrollEdit::DoMenu. The problem is that an edit view may be deleted (when the frame is closed) while its associated Undo/Redo commands are still on the OpenDoc Undo/Redo stacks. The solution we use is to reset the command’s fEditView field to 0 when it is notified of the edit view going away (see CEditViewCommand::HandleNotification), the command will still appear in the Edit menu but it will do nothing.
Content model and Selections
If you decide to make an edit view part of your content model, you need to manage the presentation’s selection object as the user selects text and you need to externalize/internalize the data. For an example see the “non official” sample part Intl Test in the Tools & Goodies folder.
2-byte character support
The same Intl Test part in Tools & Goodies shows how to use Japanese script and input method.
Miscellaneous Issues
Multiple Facets
When an edit view is visible in more than 1 facet you must force the redraw of all the other facets to see the correct text (e.g. the only facet updated by ODF Draw is the active facet receiving keyboard events).
Multiple Frames
The edit view’s content, its text, is local to the frame because it is stored by in the platform’s text edit record. If you open 2 frames of the same presentation, for example with the “View In Window” command, each frame contains its own edit views and it is up to your part to maintain a common content when it makes sense to do so.